var def_username;
var token;
// SQL语句高亮
window.onload = function() {
    var p_dbsource = getQueryString("dbsource", "");
    var p_dbsource_all = getQueryString("dbsource_all", "");

    // 初始化sql编辑器
    initSqlEditor({});
    // 初始化sql编辑器的代码提示
    initSqlEditorByApi("api/bean/table_info.json?is_subset=true&_res_type=mini");
    // 显示版本信息
    showVersion('api/job_v2/version.json', $('.title'))
    // 显示数据源
    showSelect('api/bean/dbsource.json?dbsource_all=' + p_dbsource_all, $('.dbSource'), p_dbsource, true);

    $('.CodeMirror').addClass("form-control");

    // 当 dbSource 被点击时, 将 dbSource 写入地址栏
    $(".dbSource").on("click", function() {
        var url2 = changeURLPar(window.location.href.toString(), "dbsource", $('.dbSource').val());
        window.history.pushState({},0,url2);
    });

    // 登陆相关
    def_username = $.cookie('def_username');
    token = $.cookie('token');
    if (!def_username) {
        $('#loginModal').modal({show:true,backdrop:'static',keyboard:false});
        $('.login_close').hide();
    } else {
        // 动态替换 账户名
        var sql = "--# dbsource='auto'\r\nSELECT create_time, params FROM editor_action_log where platform = 'OPEN API 低级接口' and user = '" + def_username + "' and params != 'show databases' order by id desc LIMIT 10";
        var sql_editor = window[$('.stream_sql_input').data("editor")];
        sql_editor.setValue(sql);
        $(".login_username").text(": "+ def_username);
        $.ajax({
            url : "api/user_core/login.json",
            type : "post",
            cache : false,
            dataType : "json",
            data : {username: def_username, password:$.md5(def_username+"123")}, // 临时
            success : function(res) {
                if (res.code != 200) {
                    $('#loginModal').modal({show:true,backdrop:'static',keyboard:false});
                    $('.login_close').hide();
                }
            }
        });
    }

    // 登陆
    $(".login_submit").on("click", function() {
        loginFrom("api/user_core/login.json", function(data){
            if (data && data.username) {
                $.cookie('def_username', data.username, { expires: 365 });
                if (data.token) {
                    $.cookie('token', data.token, { expires: 3 });
                }
                $(".login_username").text(": "+ data.username);
                def_username = data.username;
                var sql = "SELECT platform, create_time, params FROM editor_action_log where user = '"+def_username+"' order by id desc LIMIT 10";
                var sql_editor = window[$('.stream_sql_input').data("editor")];
                sql_editor.setValue(sql);
            }
        })
    });
    // 注销
    $(".login_out").on("click", function() {
        $(".login_username").text("");
        loginOut("api/user_core/logout.json", function(data){
            $.cookie('def_username', '', { expires: 0 });
            $('#loginModal').modal({show:true,backdrop:'static',keyboard:false});
            $('#loginModal .prompt').html('<span></span>');
            $('.login_close').hide();
        })
    });

    // 中止正在执行的任务
    $('body').on('click', '.interrupt', function(e) {
        var api = "api/job_v2/interrupt";
        var apiParam = $(this).data("param") || "";
        var _this = this, $this = $(this);
        var $input_group = $this.closest(".input-group");
        var statusKey = $input_group.data("statusKey");
        if (statusKey) {
            openApi(_this, e, api + ".json?statusKey=" + statusKey + "&user=" + def_username + apiParam);
        }
    });

    // 将当前算元格的值写入sql中, 比如  id = 1. 默认写入最后一个 from 或 where 后面.
    // TODO 暂时无法正确识别 from (select * from x where a = 1)
    $('body').on('click', '.sql_append', function(e) {
        var sql_editor = window[$(this).data("editor_id")];
        var sql = sql_editor.getValue();

        // 生成需要插入的 sql
        var field = $(this).data("field");
        var type = $(this).data("type");
        var valueObj = $(this).data("value");
        var value = type == "number" ? valueObj + "" : "'" + valueObj + "'"
        var op = $(this).data("op");
        if (op == "in") {
            value = "(" + value + ")";
        } else if (op == "like") {
            value = "'%" + valueObj + "%'";
        }
        var appendSql = " " + field + " " + op  + " " + value;


        // 当前选中内容
        var selection = sql_editor.getSelection();
        // 光标位置: {line: 1, ch: 32, sticky: 'before'} sticky 表示当前选中内容在光标的前还是后
        var cur = sql_editor.getCursor();

        if (cur && cur.sticky && cur.line + cur.ch > 0) {
            // 替换当前选中内容
            var selection2 = selection.trim().toUpperCase().replaceAll(/\s/, " ");
            if (selection2.startsWith("AND ")) {
                appendSql = " AND" + appendSql;
            } else if (selection2.startsWith("OR ")) {
                appendSql = " OR" + appendSql;
            } else if (selection2.startsWith("NOT ")) {
                appendSql = " NOT" + appendSql;
            } else if (selection2.startsWith("WHERE ")) {
                appendSql = " WHERE" + appendSql;
            } else if (selection2.startsWith("HAVING ")) {
                appendSql = " HAVING" + appendSql;
            } else if (selection2.startsWith("GROUP BY ") ) {
                if (selection2.indexOf(" HAVING ") < 0) {
                    appendSql = selection + " \r\nHAVING " + appendSql;
                } else {
                    appendSql = selection + " AND " + appendSql;
                }
            } else if (selection2.startsWith("FROM ")) {
                if (selection2.indexOf(" WHERE ") < 0 && selection2.indexOf(" HAVING ") < 0) {
                    appendSql = selection + " \r\nWHERE " + appendSql;
                } else {
                    appendSql = selection + " AND " + appendSql;
                }
            } else if (selection2.startsWith(">") || selection2.startsWith("<") || selection2.startsWith("=")  || selection2.startsWith("IN ") || selection2.startsWith("LIKE ")) {
                appendSql = " " +  op  + " " + value;
            }
            sql_editor.replaceSelection(appendSql + " ");
        } else {
            // 计算插入 sql 的位置
            var sql2 = sql.toLowerCase().replaceAll(/\s/, " ");
            var idx = -1;
            var idxFrom = sql2.lastIndexOf(" from ");
    //        if (idxFrom > 0) {
    //             idx = idx + 6;
    //        }
            var idxWhere = sql2.lastIndexOf(" where ");
            if (idxWhere > 0 && idxWhere > idxFrom) {
                 idx = idxWhere + 7;
            }
            var idxGroup = sql2.lastIndexOf(" group ");
            var idxOrder = sql2.lastIndexOf(" order ");
            var idxSkip = sql2.lastIndexOf(" skip ");
            var idxLimit = sql2.lastIndexOf(" limit ");
            var min = minIdx(idxOrder, idxGroup);
            min = minIdx(min, idxOrder);
            min = minIdx(min, idxLimit);
            if (min > idx) {
                idx = min;
            }
            if (idx <= 0) {
                idx = sql2.length;
            }

            // 生成新的 sql 并插入
            var preSql = sql2.substring(0, idx);
            if (idxWhere + 7 == idx && idxWhere > idxFrom && idx == sql2.length) {
                appendSql = " " + appendSql;
            } else if (idxWhere + 7 == idx && idxWhere > idxFrom) {
                appendSql = " " + appendSql + " AND";
            } else if (idxWhere > idxFrom) {
                appendSql = " AND" + appendSql ;
            } else {
                appendSql = " WHERE" + appendSql;
            }

            var newSql = sql.substring(0, idx) + appendSql + sql.substring(idx);
            sql_editor.setValue(newSql);
        }
    });

    // 自动注释sql
    $('body').on('click', '.commentSql', function(e) {
        var $input_group =$(this).closest(".input-group, .sybn-api-demo")
        var sql_editor = window[$input_group.find('[name=url],[name=sql]').data("editor")];
        var sql = sql_editor.getValue();
        var dbSource = $('.dbSource').val() || "";
        $.ajax({
            url: "api/sql/translate.json", type:'post', dataType:'json', async:true,
            data: { query: sql, pretty: false, dbSource:dbSource, outputType: 'commentSql'},
            //执行成功的回调函数
            success: function(data) {
                if (data && data.result && data.output && data.output != sql.trim()) {
                    sql_editor.setValue(data.output)
                }
            },
            //执行失败或错误的回调函数
            error: function(data) {
                alert("失败");
            }
        });
    });

    $('.CodeMirror').bind('keydown', 'Shift+Enter', function(event){
        if(event.keyCode == 13 && event.shiftKey){
            // Shift+Enter 提交当前sql
            event.preventDefault();
            sqlFun(event);
        } else if(event.keyCode == 191 && event.ctrlKey){
            // Ctrl+/ 注释或反注释选中代码
            event.preventDefault();

            var $this = $(this), _this = this;
            if (!$this.hasClass("btn")) {
                // 获取当前焦点同级的 defaults_action
                $this = $(document.activeElement).closest(".panel").find(".defaults_action");
            }
            var sql_editor = window[$this.closest(".input-group, .sybn-api-demo").find('[name=url],[name=sql]').data("editor")];
            var sql = sql_editor.getValue();

            var selection = sql_editor.getSelection();
            if (selection) {
                // 替换选中内容
                var selection2 = selection.trim()
                if (selection2.startsWith("/*") && selection2.endsWith("*/") ) {
                    selection = selection2.replace(/^\/\*+\s*([\s\S]*?)\s*\*+\//, "$1");
                } else if (selection2.startsWith("-- ")) {
                    selection = selection2.substr(3).trim();
                } else if (selection2.startsWith("# ")) {
                    selection = selection2.substr(2).trim();
                } else {
                    selection = "/* " + selection + "*/";
                }
                sql_editor.replaceSelection(selection)
            } else {
                // 替换当前行
                var cur = sql_editor.getCursor();
                if (cur) {
                    var lines = sql.replaceAll(/\r?\n/, "\n").split("\n");
                    var selection = lines[cur.line];
                    var selection2 = selection.trim()
                    if (selection2.startsWith("/*") && selection2.endsWith("*/") ) {
                        selection = selection2.replace(/^\/\*+\s*([\s\S]*?)\s*\*+\//, "$1");
                    } else if (selection2.startsWith("-- ")) {
                        selection = selection2.substr(3).trim();
                    } else if (selection2.startsWith("# ")) {
                        selection = selection2.substr(2).trim();
                    } else {
                        selection = "/* " + selection + "*/";
                    }
                    var cur_line = cur.line;
                    lines[cur.line] = selection;
                    sql_editor.setValue(lines.join("\n"));
                    cur = sql_editor.getCursor();
                    cur.line = cur_line;
                    sql_editor.setCursor(cur)
                    sql_editor.refresh();
                 }
            }
            return false;
        };
    });

    // 当前窗口 查询/下载
    $('body').on('click', '.sqlApi', sqlFun);
    // 新窗口 查询/下载
    $('body').on('dblclick', '.sqlApi', sqlDownloadFun);

    // 从地址栏获取sql
    var sql = getQueryString("sql");
    var sqlZip = getQueryString("zip");
    if (sqlZip) {
        sql=unzip(sqlZip);
    }
    if (sql) {
        var sql_editor = window[$('[name=url],[name=sql]').last().data("editor")];
        sql_editor.setValue(sql);
    }
};

// 设置sql
var setSqlFun = function(t) {
    var setSql;
    if (typeof t != 'string' && t.value != undefined) {
       setSql = t.value;
    }
    if (!setSql) {
      return;
    }
    var $input_group = $(t).closest(".input-group, .sybn-api-demo")
    var sql_editor = window[$input_group.find('[name=url],[name=sql]').data("editor")];
    if (sql_editor) {
        sql_editor.setValue(setSql);
    }
}

// 当前窗口 查询/下载
var sqlFun = function(e) {
    // 防止双击触发单击
    clearTimeout(sybn_time);

    var $this = $(this), _this = this;
    if (!$this.hasClass("btn")) {
        // 获取当前焦点同级的 defaults_action
        $this = $(document.activeElement).closest(".panel").find(".defaults_action");
        _this = $this[0];
    }

    // 主接口地址
    var api = $this.data("api") || "api/sql/select_v2";
    // 附加参数
    var apiParam = $this.data("param") || "";

    var $input_group = $this.closest(".input-group, .sybn-api-demo")
    var $panel_body = $this.closest(".sybn-api-demo");
    if ($panel_body.length == 0){
        $panel_body = $this.closest(".input-group");
    }
    var sql_editor = window[$input_group.find('[name=url],[name=sql]').data("editor")];
    var sql = $this.hasClass("selection") && sql_editor.getSelection() ? sql_editor.getSelection() : sql_editor.getValue();
    var sybnSqlEngine = $input_group.find('[name=sybnSqlEngine]').val();
    var sqlMaxLength = $input_group.find('[name=sqlMaxLength]').val();
    if (!sql) {
        return;
    }
    if (sql_editor.getSelection() && sql.toUpperCase().indexOf("SELECT") < 0 && sql.toUpperCase().indexOf("SHOW") <0) {
         var choice = window.confirm("当前选中的内容可能不是完整SQL, 是否继续查询当前选中内容: \r\n"  + (sql.length > 256 ? sql.substr(0,256) + "..." : sql));
         if (!choice) {
            return;
         }
    }
    if ((sql.indexOf("　") > 0 || sql.indexOf(" ") > 0)&& confirm("sql中有中文空格,是否替换为普通空格查询？\n\n请确认！")==true){
        sql = sql.replace(/ /g," ").replace(/　/g," ");
        sql_editor.setValue(sql);
    }

    // 实验行功能, 检查是否缺少逗号   "select 1 as a 2 as b" 报错 "select 1 as a, 2 as b" 不报错  "select 1 as b from (select 2 as b)" 不报错 
    var errorAs = null;
    var sqlSplit = sql.split(new RegExp("(;|\\s+from\\s+|\\s+where\\s+|\\s+skip\\s+|\\s+limit\\s+|\\s+group\\s+|\\s+having\\s+)","im"));
    for (var i = 0; i < sqlSplit.length; i++) {
        errorAs = sqlSplit[i].replace(/[a-zA-Z0-9_]+\([^()]*\)/gi, " x").replace(/[a-zA-Z0-9_]+\([^()]*\)/gi, " x").match(new RegExp("\\S+\\s+as\\s+([^,\\s]+\\s+)+\\S+\\s+as\\s+\\S+","im"));
        if (errorAs && errorAs.length > 0){
            break;
        }
    }
    if (errorAs && errorAs.length > 0){
        var errorAsSql = errorAs[0];
        if (errorAsSql.length  < 128) {
        var choice = window.confirm("当前sql可能缺少逗号, 是否继续查询当前选中内容: \r\n"  + (errorAsSql.length > 256 ? errorAsSql.substr(0,256) + "..." : errorAsSql));
            if (!choice) {
                return;
            }
        }
    }

    var sqlLow = sql.toLowerCase();
    // 有 select 和 from 没有 @ { [ ( where skip limit group having
    if (sqlLow.indexOf("select") == 0 && sqlLow.indexOf("from") > 0 && sqlLow.indexOf("@") < 0 && sqlLow.indexOf("{") < 0 && sqlLow.indexOf("[") < 0 && sqlLow.indexOf("(") < 0&& sqlLow.indexOf("where") < 0 && sqlLow.indexOf("skip") < 0 && sqlLow.indexOf("limit") < 0 && sqlLow.indexOf("group") < 0 && sqlLow.indexOf("having") < 0
        && confirm("sql中没有limit可能会返回大量结果,您真的确定要继续执行吗？\n\n请确认！")==false){
        return;
    }

    // 防止双击触发单击
    sybn_time = setTimeout(function() {
        var statusKey = "select_v2_" + new Date().getTime() + "_" + hashCode(sql)
        $input_group.find(".interrupt").show();
        $input_group.data("statusKey", statusKey);
        if($this.hasClass("mergeHead")){
            apiParam = "&_merge_head=true" + apiParam
        }
        if($this.hasClass("enable_stream")){
            apiParam = "&_enable_stream=true" + apiParam
        }
        if ($('.dbSource').val()){
            apiParam = "&dbsource=" + $('.dbSource').val() + apiParam
        }
        if (sybnSqlEngine){
            apiParam = "&sybnSqlEngine=" + sybnSqlEngine + apiParam
        }
        if (sqlMaxLength){
            apiParam = "&sqlResultMaxLength=" + sqlMaxLength + apiParam
        }
        apiParam = "&statusKey=" + statusKey + "&user=" + def_username + apiParam;

        // 替换地址栏的url, 方便复制
        var url2 = window.location.href.toString()
        if($this.hasClass("char")){
            url2 = changeURLPar(url2, "_result_view", getViewParam($panel_body));
        }
        url2 = changeURLPar(url2, "zip", zip(sql));
        window.history.pushState({},0,url2);

        if($this.hasClass("excel")){
            sqlWindowOpenFun(api, ".xlsx", sql, apiParam);
        } else if($this.hasClass("csv")){
            sqlWindowOpenFun(api, ".csv", sql, apiParam);
        } else if($this.hasClass("debug")){
            openApi(_this, e, api + ".json?_is_debug=true" + apiParam, {sql:sql});
        } else if($this.hasClass("char")){
            var view = getViewParam($panel_body);
            var url = api + ".json?sql=" + encodeURIComponent(sql) + "&_result_view=" + view + apiParam;
            $panel_body.find(".char_view").find(".chars_preview").remove();
            $panel_body.find(".char_view").append("<div class='chars_preview clear_both' id='container' style='height:300px;width:100%'></div>");
            var chartsType = $panel_body.find('[name=result_view_charts_type]').val()
            showCharts(url, $panel_body.find(".chars_preview"), chartsType);
        } else {
            openApi(_this, e, api + ".json?" + apiParam, {sql:sql})
        }
    }, 300);
};

// 新窗口 查询/下载
var sqlDownloadFun = function(e) {
    // 防止双击触发单击
    clearTimeout(sybn_time);

    var $this = $(this);
    if (!$this.hasClass("btn")) {
        // 获取当前焦点同级的 defaults_action
        $this = $(document.activeElement).closest(".panel").find(".defaults_action");
    }
    // $(document.activeElement)

    // 主接口地址
    var api = $this.data("api") || "api/sql/select_v2";
    // 附加参数
    var apiParam = $this.data("param") || "";

    var $input_group = $this.closest(".input-group, .sybn-api-demo")
    var $panel_body = $this.closest(".sybn-api-demo");
    if ($panel_body.length == 0){
        $panel_body = $this.closest(".input-group");
    }

    var sql_editor = window[$input_group.find('[name=url],[name=sql]').data("editor")];
    var sql = $this.hasClass("selection") && sql_editor.getSelection() ? sql_editor.getSelection() : sql_editor.getValue();
    var sybnSqlEngine = $input_group.find('[name=sybnSqlEngine]').val();
    var sqlMaxLength = $input_group.find('[name=sqlMaxLength]').val();
    if (!sql) {
        return;
    }
    if (sql_editor.getSelection() && sql.toUpperCase().indexOf("SELECT") < 0 && sql.toUpperCase().indexOf("SHOW") <0) {
         var choice = window.confirm("当前选中的内容可能不是完整SQL, 是否继续查询当前选中内容: \r\n"  + (sql.length > 256 ? sql.substr(0,256) + "..." : sql));
         if (!choice) {
            return;
         }
    }
    if ((sql.indexOf("　") > 0 || sql.indexOf(" ") > 0)&& confirm("sql中有中文空格,是否替换为普通空格查询？\n\n请确认！")==true){
        sql = sql.replace(/ /g," ").replace(/　/g," ");
        sql_editor.setValue(sql);
    }

    // 实验行功能, 检查是否缺少逗号
    var errorAs = sql.replace(/[a-zA-Z0-9_]+\([^()]*\)/gi, " x").replace(/[a-zA-Z0-9_]+\([^()]*\)/gi, " x").match(new RegExp("\\S+\\s+as\\s+[^,]+\\s+\\S+\\s+as\\s+\\S+","im"));
    if (errorAs && errorAs.length > 0){
        var errorAsSql = errorAs[0];
        if (errorAsSql.length  < 128) {
        var choice = window.confirm("当前sql可能缺少逗号, 是否继续查询当前选中内容: \r\n"  + (errorAsSql.length > 256 ? errorAsSql.substr(0,256) + "..." : errorAsSql));
            if (!choice) {
                return;
            }
        }
    }

    var sqlLow = sql.toLowerCase();
    // 有 select 和 from 没有 @ { [ ( where skip limit group having
    if (sqlLow.indexOf("select") == 0 && sqlLow.indexOf("from") > 0 && sqlLow.indexOf("@")<0 && sqlLow.indexOf("{") <0 && sqlLow.indexOf("[")<0 && sqlLow.indexOf("(") < 0&& sqlLow.indexOf("where") < 0 && sqlLow.indexOf("skip") < 0 && sqlLow.indexOf("limit") < 0 && sqlLow.indexOf("group") < 0 && sqlLow.indexOf("having") < 0
        && confirm("sql中没有limit可能会返回大量结果,您真的确定要继续执行吗？\n\n请确认！")==false){
        return;
    }

    var statusKey = "select_v2_" + new Date().getTime() + "_" + hashCode(sql)
    $input_group.find(".interrupt").show();
    $input_group.data("statusKey", statusKey);
    if($this.hasClass("mergeHead")){
        apiParam = "&_merge_head=true" + apiParam
    }
    if($this.hasClass("enable_stream")){
        apiParam = "&_enable_stream=true" + apiParam
    }
    if ($('.dbSource').val()){
        apiParam = "&dbsource=" + $('.dbSource').val() + apiParam
    }
    if (sybnSqlEngine){
        apiParam = "&sybnSqlEngine=" + sybnSqlEngine + apiParam
    }
    if (sqlMaxLength){
        apiParam = "&sqlResultMaxLength=" + sqlMaxLength + apiParam
    }
    apiParam = "&statusKey=" + statusKey + "&user=" + def_username + apiParam;
    if($this.hasClass("excel")){
        sqlWindowOpenFun.open(api, ".xlsx", sql, apiParam);
    } else if($this.hasClass("csv")){
        sqlWindowOpenFun.open(api, ".csv", sql, apiParam);
    } else if($this.hasClass("debug")){
        sqlWindowOpenFun(api, ".json", sql, "_is_debug=true&" + apiParam);
    } else if($this.hasClass("char")){
        $panel_body.find(".char_view ").append("<div class='iframe_preview clear_both' id='container' style='height:300px;width:100%'></div>");
        var view = getViewParam($panel_body);
        var url = api + ".json?sql=" + encodeURIComponent(sql) + "&_result_view=" + view + apiParam;
        var chartsType = $panel_body.find('[name=result_view_charts_type]').val()
        showCharts(url, $panel_body.find( ".chars_preview"), chartsType);
    } else {
        sqlWindowOpenFun.open(api, ".json", sql, apiParam);
    }
}


var sqlWindowOpenFun = function(api, extName, sql, apiParam) {
    var url = api + extName + "?sql=" + encodeURIComponent(sql) + apiParam;
    if (url.length < 20480) {
        window.open(url);
        return;
    }
    postBlank(api + extName + "?" + apiParam, {sql:sql});

}